<head><meta charset="utf-8" /><style  type="text/css">:root {
    --side-bar-bg-color: #fafafa;
    --control-text-color: #777;
}

@include-when-export url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext);

@font-face {
    font-family: 'Open Sans';
    font-style: normal;
    font-weight: normal;
    src: local('Open Sans Regular'),url('./github/400.woff') format('woff')
}

@font-face {
    font-family: 'Open Sans';
    font-style: italic;
    font-weight: normal;
    src: local('Open Sans Italic'),url('./github/400i.woff') format('woff')
}

@font-face {
    font-family: 'Open Sans';
    font-style: normal;
    font-weight: bold;
    src: local('Open Sans Bold'),url('./github/700.woff') format('woff')
}

@font-face {
    font-family: 'Open Sans';
    font-style: italic;
    font-weight: bold;
    src: local('Open Sans Bold Italic'),url('./github/700i.woff') format('woff')
}

html {
    font-size: 16px;
}

body {
    font-family: "Open Sans","Clear Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
    color: rgb(51, 51, 51);
    line-height: 1.6;
}

#write{
    max-width: 860px;
  	margin: 0 auto;
  	padding: 20px 30px 40px 30px;
	padding-top: 20px;
    padding-bottom: 100px;
}
#write > ul:first-child,
#write > ol:first-child{
    margin-top: 30px;
}

body > *:first-child {
    margin-top: 0 !important;
}
body > *:last-child {
    margin-bottom: 0 !important;
}
a {
    color: #4183C4;
}
h1,
h2,
h3,
h4,
h5,
h6 {
    position: relative;
    margin-top: 1rem;
    margin-bottom: 1rem;
    font-weight: bold;
    line-height: 1.4;
    cursor: text;
}
h1:hover a.anchor,
h2:hover a.anchor,
h3:hover a.anchor,
h4:hover a.anchor,
h5:hover a.anchor,
h6:hover a.anchor {
    /*background: url("../../images/modules/styleguide/para.png") no-repeat 10px center;*/
    text-decoration: none;
}
h1 tt,
h1 code {
    font-size: inherit;
}
h2 tt,
h2 code {
    font-size: inherit;
}
h3 tt,
h3 code {
    font-size: inherit;
}
h4 tt,
h4 code {
    font-size: inherit;
}
h5 tt,
h5 code {
    font-size: inherit;
}
h6 tt,
h6 code {
    font-size: inherit;
}
h1 {
    padding-bottom: .3em;
    font-size: 2.25em;
    line-height: 1.2;
    border-bottom: 1px solid #eee;
}
h2 {
   padding-bottom: .3em;
    font-size: 1.75em;
    line-height: 1.225;
    border-bottom: 1px solid #eee;
}
h3 {
    font-size: 1.5em;
    line-height: 1.43;
}
h4 {
    font-size: 1.25em;
}
h5 {
    font-size: 1em;
}
h6 {
   font-size: 1em;
    color: #777;
}
p,
blockquote,
ul,
ol,
dl,
table{
    margin: 0.8em 0;
}
li>ol,
li>ul {
    margin: 0 0;
}
hr {
    height: 2px;
    padding: 0;
    margin: 16px 0;
    background-color: #e7e7e7;
    border: 0 none;
    overflow: hidden;
    box-sizing: content-box;
}

body > h2:first-child {
    margin-top: 0;
    padding-top: 0;
}
body > h1:first-child {
    margin-top: 0;
    padding-top: 0;
}
body > h1:first-child + h2 {
    margin-top: 0;
    padding-top: 0;
}
body > h3:first-child,
body > h4:first-child,
body > h5:first-child,
body > h6:first-child {
    margin-top: 0;
    padding-top: 0;
}
a:first-child h1,
a:first-child h2,
a:first-child h3,
a:first-child h4,
a:first-child h5,
a:first-child h6 {
    margin-top: 0;
    padding-top: 0;
}
h1 p,
h2 p,
h3 p,
h4 p,
h5 p,
h6 p {
    margin-top: 0;
}
li p.first {
    display: inline-block;
}
ul,
ol {
    padding-left: 30px;
}
ul:first-child,
ol:first-child {
    margin-top: 0;
}
ul:last-child,
ol:last-child {
    margin-bottom: 0;
}
blockquote {
    border-left: 4px solid #dfe2e5;
    padding: 0 15px;
    color: #777777;
}
blockquote blockquote {
    padding-right: 0;
}
table {
    padding: 0;
    word-break: initial;
}
table tr {
    border-top: 1px solid #dfe2e5;
    margin: 0;
    padding: 0;
}
table tr:nth-child(2n),
thead {
    background-color: #f8f8f8;
}
table tr th {
    font-weight: bold;
    border: 1px solid #dfe2e5;
    border-bottom: 0;
    text-align: left;
    margin: 0;
    padding: 6px 13px;
}
table tr td {
    border: 1px solid #dfe2e5;
    text-align: left;
    margin: 0;
    padding: 6px 13px;
}
table tr th:first-child,
table tr td:first-child {
    margin-top: 0;
}
table tr th:last-child,
table tr td:last-child {
    margin-bottom: 0;
}

.CodeMirror-lines {
    padding-left: 4px;
}

.code-tooltip {
    box-shadow: 0 1px 1px 0 rgba(0,28,36,.3);
    border-top: 1px solid #eef2f2;
}

.md-fences,
code,
tt {
    border: 1px solid #e7eaed;
    background-color: #f8f8f8;
    border-radius: 3px;
    padding: 0;
    padding: 2px 4px 0px 4px;
    font-size: 0.9em;
}

code {
    background-color: #f3f4f4;
    padding: 0 4px 2px 4px;
}

.md-fences {
    margin-bottom: 15px;
    margin-top: 15px;
    padding: 0.2em 1em;
    padding-top: 8px;
    padding-bottom: 6px;
}


.md-task-list-item > input {
  margin-left: -1.3em;
}

@media screen and (min-width: 914px) {
    /*body {
        width: 854px;
        margin: 0 auto;
    }*/
}
@media print {
    html {
        font-size: 13px;
    }
    table,
    pre {
        page-break-inside: avoid;
    }
    pre {
        word-wrap: break-word;
    }
}

.md-fences {
	background-color: #f8f8f8;
}
#write pre.md-meta-block {
	padding: 1rem;
    font-size: 85%;
    line-height: 1.45;
    background-color: #f7f7f7;
    border: 0;
    border-radius: 3px;
    color: #777777;
    margin-top: 0 !important;
}

.mathjax-block>.code-tooltip {
	bottom: .375rem;
}

.md-mathjax-midline {
    background: #fafafa;
}

#write>h3.md-focus:before{
	left: -1.5625rem;
	top: .375rem;
}
#write>h4.md-focus:before{
	left: -1.5625rem;
	top: .285714286rem;
}
#write>h5.md-focus:before{
	left: -1.5625rem;
	top: .285714286rem;
}
#write>h6.md-focus:before{
	left: -1.5625rem;
	top: .285714286rem;
}
.md-image>.md-meta {
    /*border: 1px solid #ddd;*/
    border-radius: 3px;
    padding: 2px 0px 0px 4px;
    font-size: 0.9em;
    color: inherit;
}

.md-tag {
    color: #a7a7a7;
    opacity: 1;
}

.md-toc {
    margin-top:20px;
    padding-bottom:20px;
}

.sidebar-tabs {
    border-bottom: none;
}

#typora-quick-open {
    border: 1px solid #ddd;
    background-color: #f8f8f8;
}

#typora-quick-open-item {
    background-color: #FAFAFA;
    border-color: #FEFEFE #e5e5e5 #e5e5e5 #eee;
    border-style: solid;
    border-width: 1px;
}

/** focus mode */
.on-focus-mode blockquote {
    border-left-color: rgba(85, 85, 85, 0.12);
}

header, .context-menu, .megamenu-content, footer{
    font-family: "Segoe UI", "Arial", sans-serif;
}

.file-node-content:hover .file-node-icon,
.file-node-content:hover .file-node-open-state{
    visibility: visible;
}

.mac-seamless-mode #typora-sidebar {
    background-color: #fafafa;
    background-color: var(--side-bar-bg-color);
}

.md-lang {
    color: #b4654d;
}

.html-for-mac .context-menu {
    --item-hover-bg-color: #E6F0FE;
}</style></head><h3>Cinder</h3>
<ul>
<li>Cinder在OpenStack中为虚拟机实例提供volume的块存储服务，可将卷挂载到实例上，作为虚拟机实例的本地磁盘使用。<ul>
<li><strong>组件化</strong>：便于添加新功能</li>
<li><strong>高可用</strong>：能承受高负载</li>
<li><strong>容错</strong>：隔离机制避免级联故障</li>
<li><strong>可恢复</strong>：简便及时的故障检测与恢复</li>
<li><strong>开放标准</strong>：提供标准实现，为社区提供参考</li>
</ul>
</li>
</ul>
<h4>主要模块</h4>
<p><img alt="image" src="http://www.99cloud.net/wp-content/uploads/2019/04/7-1554090785.jpg"></p>
<h5>cinder-api</h5>
<ul>
<li>对外提供稳定而统一的北向 RESTful API，cinder-api service 服务进程通常运行在控制节点，支持多 Workers 进程（通过配置项 osapivolumeworkers 设定）。接收到的合法请求会经由 MQ 传递到 cinder-volume 执行。Cinder API 现存 v2(DEPRECATED)、v3(CURRENT) 两个版本，可以通过配置文件来启用。</li>
<li>官方API介绍：https://developer.openstack.org/api-ref/block-storage/</li>
</ul>
<h6>核心流程</h6>
<ul>
<li>创建 Volume  的流程：<ul>
<li>cinder-api 创建 volume_create_api 工作流（flow） <ul>
<li>ExtractVolumeRequestTask：获取（Extract）、验证（Validates）create volume 在 cinder-api 阶段相关的信息</li>
<li>QuotaReserverTask：预留配额</li>
<li>EntryCreateTask：在数据库中创建 Volumn 条目</li>
<li>QuotaCommitTask：确认配额 </li>
<li>VolumeCastTask：发出一个 Cast 异步请求，将创建请求丢到 MQ，最终被 cinder-scheduler service 接收</li>
</ul>
</li>
<li>cinder-scheduler 启动一个 volume_create_scheduler flow<ul>
<li>ExtractSchedulerSpecTask：将 request body 转换成为 Scheduler Filter 中通用的 RequestSpec 数据结构（实例对象）。</li>
<li>SchedulerCreateVolumeTask：完成 Filter 和 Weight 的调度算法。</li>
</ul>
</li>
<li>RPC 请求发送到 cinder-volume service 接收</li>
<li>cinder-volume 启动工作流 volume_create_manager：<ul>
<li>ExtractVolumeRefTask ： 解析请求体</li>
<li>OnFailureRescheduleTask：</li>
<li>ExtractVolumeSpecTask：将 request body 转换成为 Volume 模块中通用的 RequestSpec 数据结构（实例对象）</li>
<li>NotifyVolumeActionTask：当对已有的卷采取措施的时候发送相应的通知 </li>
<li>CreateVolumeFromSpecTask：创建对应的卷 </li>
<li>CreateVolumeFromSpecTask：执行创建成功之后的后续操作 </li>
</ul>
</li>
</ul>
</li>
<li>创建 Volume 的方式</li>
<li>建立raw格式的新卷</li>
<li>从快照建立新卷</li>
<li>从已有卷建立新卷</li>
<li>从副本建立新卷</li>
<li>从镜像建立新卷</li>
</ul>
<h6>细节</h6>
<p>根据现在最新的<a href="https://developer.openstack.org/api-ref/block-storage/v3/index.html"> V3 </a>版本的 API总结如下:
- <a href="https://github.com/openstack/cinder/blob/master/cinder/db/sqlalchemy/models.py">Github: Volume 资源模型</a>
- Volumn Type 主要是针对多后端存储进行卷类型的管理<br>
<img alt="image" src="https://img-blog.csdnimg.cn/20190225183417599.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0ptaWxr,size_16,color_FFFFFF,t_70"><br>
- Volumes 针对 卷 来进行管理。其中一个卷（Volume）类似于一个如USB硬盘的可插拔的块存储设备，每一次可以将卷对应的挂载到实例上。
    - 对 Volumes 设备进行 CRUD 时，对应的会有很多种状态，可以参考对应官方文档中的状态表。
    - CRUD of Cinder Volumn</p>
<h6>CRUD of Cinder Volumn</h6>
<ul>
<li>POST  <code>/v3/{project_id}/volumes</code> Request Body  </li>
</ul>
<pre><code class="JSON">{
    &quot;volume&quot;: {
        &quot;size&quot;: 10,      //int The size of the volume, in gibibytes (GiB).
        &quot;availability_zone&quot;: null, //The name of the availability zone.
        &quot;source_volid&quot;: null, //The UUID of the source volume.
        &quot;description&quot;: null, //The volume description.
        &quot;multiattach&quot;: false, //To enable this volume to attach to more than one server, set this value to true. Default is false.
        &quot;snapshot_id&quot;: null, //The UUID of the volume snapshot
        &quot;backup_id&quot;: null, //The UUID of the backup.
        &quot;name&quot;: null, //The volume name.
        &quot;imageRef&quot;: null, //The UUID of the image from which you want to create the volume. 
        &lt;!--&quot;volume_type&quot;: null, //The volume type (either name or ID). 
        &quot;metadata&quot;: {}, //One or more metadata key and value pairs to be associated with the new volume.
        &quot;consistencygroup_id&quot;: null //The UUID of the consistency group.
    },
    &quot;OS-SCH-HNT:scheduler_hints&quot;: { //The dictionary of data to send to the scheduler.
        &quot;same_host&quot;: [
            &quot;a0cf03a5-d921-4877-bb5c-86d26cf818e1&quot;,
            &quot;8c19174f-4220-44f0-824a-cd1eeef10287&quot;
        ]
    }
}
</code></pre>

<ul>
<li>POST <code>/v3/{project_id}/volumes</code> Response Body</li>
</ul>
<pre><code class="JSON">{
    &quot;volume&quot;: {
        &quot;attachments&quot;: [], //Instance attachment information.(Server/Host/Device/Volume)
        &quot;availability_zone&quot;: &quot;nova&quot;,//The name of the availability zone.
        &quot;bootable&quot;: &quot;false&quot;,//Enables or disables the bootable attribute. You can boot an instance from a bootable volume.
        &quot;consistencygroup_id&quot;: null,//The UUID of the consistency group.
        &quot;created_at&quot;: &quot;2018-11-28T06:21:12.715987&quot;,//The date and time when the resource was created.CCYY-MM-DDThh:mm:ss±hh:mm
        &quot;description&quot;: null, //The volume description.
        &quot;encrypted&quot;: false, //If true, this volume is encrypted.
        &quot;id&quot;: &quot;2b955850-f177-45f7-9f49-ecb2c256d161&quot;,//The UUID of the volume.
        &quot;links&quot;: [ //The volume links.
            {
                &quot;href&quot;: &quot;http://127.0.0.1:33951/v3/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/2b955850-f177-45f7-9f49-ecb2c256d161&quot;,
                &quot;rel&quot;: &quot;self&quot;
            },
            {
                &quot;href&quot;: &quot;http://127.0.0.1:33951/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/2b955850-f177-45f7-9f49-ecb2c256d161&quot;,
                &quot;rel&quot;: &quot;bookmark&quot;
            }
        ],
        &quot;metadata&quot;: {},//A metadata object. Contains one or more metadata key and value pairs that are associated with the volume.
        &quot;migration_status&quot;: null,
        &quot;multiattach&quot;: false,//If true, this volume can attach to more than one instance.
        &quot;name&quot;: null,//The volume name.
        &quot;replication_status&quot;: null,//The volume replication status.
        &quot;size&quot;: 10,//The size of the volume, in gibibytes (GiB).
        &quot;snapshot_id&quot;: null,// The UUID of the volume snapshot
        &quot;source_volid&quot;: null,//The UUID of the source volume.
        &quot;status&quot;: &quot;creating&quot;,//The volume status.
        &quot;updated_at&quot;: null, //The date and time when the resource was updated. CCYY-MM-DDThh:mm:ss±hh:mm
        &quot;user_id&quot;: &quot;c853ca26-e8ea-4797-8a52-ee124a013d0e&quot;,//The UUID of the user.
        &quot;volume_type&quot;: null //The associated volume type for the volume.
    }
</code></pre>

<ul>
<li>GET <code>/v3/{project_id}/volumes</code> (List accessible volumes) Response Body</li>
</ul>
<pre><code class="JSON">{
    &quot;volumes&quot;: [
        {
            &quot;id&quot;: &quot;efa54464-8fab-47cd-a05a-be3e6b396188&quot;,
            &quot;links&quot;: [
                {
                    &quot;href&quot;: &quot;http://127.0.0.1:37097/v3/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/efa54464-8fab-47cd-a05a-be3e6b396188&quot;,
                    &quot;rel&quot;: &quot;self&quot;
                },
                {
                    &quot;href&quot;: &quot;http://127.0.0.1:37097/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/efa54464-8fab-47cd-a05a-be3e6b396188&quot;,
                    &quot;rel&quot;: &quot;bookmark&quot;
                }
            ],
            &quot;name&quot;: null
        }
    ]
}
</code></pre>

<ul>
<li>GET <code>/v3/{project_id}/volumes/{volume_id}</code> Response Body</li>
</ul>
<pre><code class="JSON">{
    &quot;volume&quot;: {
        &quot;attachments&quot;: [],
        &quot;availability_zone&quot;: &quot;nova&quot;,
        &quot;bootable&quot;: &quot;false&quot;,
        &quot;consistencygroup_id&quot;: null,
        &quot;created_at&quot;: &quot;2018-11-29T06:50:07.770785&quot;,
        &quot;description&quot;: null,
        &quot;encrypted&quot;: false,
        &quot;id&quot;: &quot;f7223234-1afc-4d19-bfa3-d19deb6235ef&quot;,
        &quot;links&quot;: [
            {
                &quot;href&quot;: &quot;http://127.0.0.1:45839/v3/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/f7223234-1afc-4d19-bfa3-d19deb6235ef&quot;,
                &quot;rel&quot;: &quot;self&quot;
            },
            {
                &quot;href&quot;: &quot;http://127.0.0.1:45839/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/f7223234-1afc-4d19-bfa3-d19deb6235ef&quot;,
                &quot;rel&quot;: &quot;bookmark&quot;
            }
        ],
        &quot;metadata&quot;: {},
        &quot;migration_status&quot;: null,
        &quot;multiattach&quot;: false,
        &quot;name&quot;: null,
        &quot;os-vol-host-attr:host&quot;: null,//Current back-end of the volume. Host format is host@backend#pool.
        &quot;os-vol-mig-status-attr:migstat&quot;: null,//The status of this volume migration (None means that a migration is not currently in progress).
        &quot;os-vol-mig-status-attr:name_id&quot;: null,//The volume ID that this volume name on the back- end is based on.
        &quot;os-vol-tenant-attr:tenant_id&quot;: &quot;89afd400-b646-4bbc-b12b-c0a4d63e5bd3&quot;,//The project ID which the volume belongs to.
        &quot;replication_status&quot;: null,
        &quot;size&quot;: 10,
        &quot;snapshot_id&quot;: null,
        &quot;source_volid&quot;: null,
        &quot;status&quot;: &quot;creating&quot;,
        &quot;updated_at&quot;: null,
        &quot;user_id&quot;: &quot;c853ca26-e8ea-4797-8a52-ee124a013d0e&quot;,
        &quot;volume_type&quot;: null
    }
}
</code></pre>

<ul>
<li>PUT <code>/v3/{project_id}/volumes/{volume_id}</code> Request Body</li>
</ul>
<pre><code class="JSON">{
    &quot;volume&quot;: {
        &quot;name&quot;: &quot;vol-003&quot;,
        &quot;description&quot;: &quot;This is yet, another volume.&quot;,
        &quot;metadata&quot;: {
            &quot;name&quot;: &quot;metadata0&quot;
        }
    }
}
</code></pre>

<ul>
<li>DELETE <code>/v3/{project_id}/volumes/{volume_id}</code><ul>
<li>Preconditions: status available, in-use, error, error_restoring, error_extending, error_managing.</li>
<li>Async Postconditions: Delete index and volumn on storage node.</li>
</ul>
</li>
</ul>
<h6>CRUD of Cinder Volumn metadata</h6>
<ul>
<li>POST <code>/v3/{project_id}/volumes/{volume_id}/metadata</code> Request Body (Same with response)</li>
</ul>
<pre><code class="JSON">{
    &quot;metadata&quot;: {
        &quot;name&quot;: &quot;metadata0&quot;
    }
}
</code></pre>

<ul>
<li>GET <code>/v3/{project_id}/volumes/{volume_id}/metadata</code></li>
<li>PUT <code>/v3/{project_id}/volumes/{volume_id}/metadata</code> </li>
<li>GET <code>/v3/{project_id}/volumes/{volume_id}/metadata/{key}</code> //Show a volume’s metadata for a specific key</li>
<li>DELETE <code>/v3/{project_id}/volumes/{volume_id}/metadata/{key}</code></li>
<li>PUT <code>/v3/{project_id}/volumes/{volume_id}/metadata/{key}</code></li>
<li>GET <code>/v3/{project_id}/volumes/summary</code> Response Body //Get volumes summary </li>
</ul>
<pre><code class="JSON">{
    &quot;volume-summary&quot;: {
        &quot;total_size&quot;: 4,
        &quot;total_count&quot;: 4,
        &quot;metadata&quot;: {
            &quot;key1&quot;: [&quot;value1&quot;, &quot;value2&quot;],
            &quot;key2&quot;: [&quot;value2&quot;]
        }
    }
}
</code></pre>

<h6>Volume manage extension (manageable_volumes)¶</h6>
<ul>
<li>POST <code>/v3/{project_id}/manageable_volumes</code> </li>
<li>Creates a Block Storage volume by using existing storage rather than allocating new storage.</li>
</ul>
<pre><code class="JSON">Request
{
    &quot;volume&quot;: {
        &quot;host&quot;: &quot;geraint-VirtualBox&quot;,
        &quot;ref&quot;: {
            &quot;source-name&quot;: &quot;existingLV&quot;,
            &quot;source-id&quot;: &quot;1234&quot;
        },
        &quot;name&quot;: &quot;New Volume&quot;,
        &quot;availability_zone&quot;: &quot;az2&quot;,
        &quot;description&quot;: &quot;Volume imported from existingLV&quot;,
        &quot;volume_type&quot;: null,
        &quot;bootable&quot;: true,
        &quot;metadata&quot;: {
            &quot;key1&quot;: &quot;value1&quot;,
            &quot;key2&quot;: &quot;value2&quot;
        }
    }
}
</code></pre>

<ul>
<li>GET <code>/v3/{project_id}/manageable_volumes</code> List summary of volumes available to manage</li>
</ul>
<pre><code class="JSON">Response
{
    &quot;manageable-volumes&quot;: [
        {
            &quot;safe_to_manage&quot;: false,
            &quot;reference&quot;: {
                &quot;source-name&quot;: &quot;volume-3a81fdac-e8ae-4e61-b6a2-2e14ff316f19&quot;
            },
            &quot;size&quot;: 1
        },
        {
            &quot;safe_to_manage&quot;: true,
            &quot;reference&quot;: {
                &quot;source-name&quot;: &quot;lvol0&quot;
            },
            &quot;size&quot;: 1
        }
    ]
}
</code></pre>

<ul>
<li>GET <code>/v3/{project_id}/manageable_volumes/detail</code> List detail of volumes available to manage</li>
</ul>
<pre><code class="JSON">Response
{
    &quot;manageable-volumes&quot;: [
        {
            &quot;cinder_id&quot;: &quot;9ba5bb53-4a18-4b38-be06-992999da338d&quot;,
            &quot;reason_not_safe&quot;: &quot;already managed&quot;,
            &quot;reference&quot;: {
                &quot;source-name&quot;: &quot;volume-9ba5bb53-4a18-4b38-be06-992999da338d&quot;
            },
            &quot;safe_to_manage&quot;: false,
            &quot;size&quot;: 1,
            &quot;extra_info&quot;: null
        },
        {
            &quot;cinder_id&quot;: null,
            &quot;reason_not_safe&quot;: null,
            &quot;reference&quot;: {
                &quot;source-name&quot;: &quot;lvol0&quot;
            },
            &quot;safe_to_manage&quot;: true,
            &quot;size&quot;: 1,
            &quot;extra_info&quot;: null
        }
    ]
}
</code></pre>

<h6>Volume transfer</h6>
<ul>
<li>Transfers a volume from one user to another user.</li>
</ul>
<h6>Services (os-services)¶</h6>
<ul>
<li>Administrator only. Lists all Cinder services, enables or disables a Cinder service, freeze or thaw the specified cinder-volume host, failover a replicating cinder-volume host.</li>
</ul>
<h6>Volume actions (volumes, action)¶</h6>
<ul>
<li>POST <code>/v3/{project_id}/volumes/{volume_id}/action</code></li>
</ul>
<pre><code class="JSON">{
    // Extend the size
    &quot;os-extend&quot;: {
        &quot;new_size&quot;: 3
    }

    // Reset a volume’s statuses
    &quot;os-reset_status&quot;: {
        &quot;status&quot;: &quot;available&quot;,
        &quot;attach_status&quot;: &quot;detached&quot;,
        &quot;migration_status&quot;: &quot;migrating&quot;
    }

    // Revert volume to snapshot
    &quot;revert&quot;: {
        &quot;snapshot_id&quot;: &quot;5aa119a8-d25b-45a7-8d1b-88e127885635&quot;
    }

    // Set image metadata for a volume
    &quot;os-set_image_metadata&quot;: {
        &quot;metadata&quot;: {
            &quot;image_id&quot;: &quot;521752a6-acf6-4b2d-bc7a-119f9148cd8c&quot;,
            &quot;image_name&quot;: &quot;image&quot;,
            &quot;kernel_id&quot;: &quot;155d900f-4e14-4e4c-a73d-069cbf4541e6&quot;,
            &quot;ramdisk_id&quot;: &quot;somedisk&quot;
        }
    }

    // Remove image metadata from a volume
    &quot;os-unset_image_metadata&quot;: {
        &quot;key&quot;: &quot;ramdisk_id&quot;
    }

    // Show image metadata for a volume
    &quot;os-show_image_metadata&quot;: {}

    // Attach volume to a server
    &quot;os-attach&quot;: {
        &quot;instance_uuid&quot;: &quot;95D9EF50-507D-11E5-B970-0800200C9A66&quot;, //The UUID of the attaching instance.
        &quot;mountpoint&quot;: &quot;/dev/vdc&quot; //The attaching mount point.
    }

    // Detach volume from server
    &quot;os-detach&quot;: {
        &quot;attachment_id&quot;: &quot;d8777f54-84cf-4809-a679-468ffed56cf1&quot;
    }

    // Unmanage a volume
    &quot;os-unmanage&quot;: {}

    // Force detach a volume
    &quot;os-force_detach&quot;: {
        &quot;attachment_id&quot;: &quot;d8777f54-84cf-4809-a679-468ffed56cf1&quot;,
        &quot;connector&quot;: {
            &quot;initiator&quot;: &quot;iqn.2012-07.org.fake:01&quot;
        }
    }

    //Retype a volume
    //Migrate a volume
    //Complete migration of a volume
    //Force delete a volume
    //Update a volume’s bootable status
    //Upload volume to image
    //Reserve volume
    //Unmark volume as reserved.
    //Update volume status to detaching
    //Roll back volume status to in-use
    //Terminate volume attachment
    //Initialize volume attachment
    //Updates volume read-only access-mode flag
    ...
}
</code></pre>

<h6>Generic volume groups</h6>
<ul>
<li>Generic volume groups enable you to create a group of volumes and manage them together.</li>
</ul>
<h5>cinder-scheduler</h5>
<ul>
<li>
<p>如果说 cinder-api 接收的是关于 “创建” 的请求（e.g. Create Volume），那么该请求就会通过 MQ 转发到 cinder-scheduler service 服务进程，cinder-scheduler 与 nova-scheduler 一般，顾名思义是调度的层面。通过 Filters 选择最 “合适” 的 Storage Provider Node 来对请求资源（e.g. Volume）进行创建。不同的 Filters 具有不同的过滤（调度）算法，所谓的 “合适” 就是达到客户预期的结果，用户还可以自定义 Filter Class 来实现符合自身需求的过滤器，让调度更加灵活。与 nova-scheduler 一般，cinder-scheduler 同样需要维护调度对象（存储节点）“实时” 状态，cinder-volume service 会定期的向 cinder-scheduler service 上报存储节点状态（注：这实际上是通过后端存储设备的驱动程序上报了该设备的状态）。</p>
<ul>
<li>首先判断存储节点状态，只有状态为 up 的存储节点才会被考虑。</li>
<li>创建 Volume 时，根据 Filter 和 Weight 算法选出最优存储节点。</li>
<li>迁移 Volume 时，根据 Filter 和 Weight 算法来判断目的存储节点是否符合要求。</li>
</ul>
</li>
</ul>
<h5>cinder-volume</h5>
<ul>
<li>cinder-volume service 是 Cinder 的核心服务进程，运行该服务进程的节点都可以被称之为存储节点。cinder-volume 通过抽象出统一的 Back-end Storage Driver 层，让不同存储厂商得以通过提供各自的驱动程序来对接自己的后端存储设备，实现即插即用（通过配置文件指定），多个这样的存储节点共同构成了一个庞大而复杂多样的存储资源池系统。</li>
</ul>
<h6>cinder-volumn Driver</h6>
<ul>
<li>OpenStack 作为开放的 Infrastracture as a Service 云操作系统，支持业界各种优秀的技术，这些技术可能是开源免费的，也可能是商业收费的。 这种开放的架构使得 OpenStack 保持技术上的先进性，具有很强的竞争力，同时又不会造成厂商锁定（Lock-in）。</li>
<li>以 Cinder 为例，存储节点支持多种 Volume Provider，包括 LVM、NFS、Ceph、GlusterFS 以及 EMC、IBM 等商业存储系统。 cinder-volume 为这些 Volume Provider 抽象了统一的 Driver 接口，Volume Provider 只需要实现这些接口，就可以以 Driver 的形式即插即（volume_driver 配置项）用到 OpenStack 中。下面是 Cinder Driver 的架构示意图：<br>
<img alt="image" src="http://www.99cloud.net/wp-content/uploads/2019/04/4-1554090785.jpg"></li>
</ul>
<h5>cinder-volumn Plugin</h5>
<ul>
<li>Driver 和 Plugin 通常不会分家，Driver 是由各存储厂商提供的，那么 Plugins（插槽）就应该有 Cinder 的提供。 根据 FileSystem Storage 和 Block Storage 两个不同类型的外部存储系统，Cinder Plugins 也提供了 FileSystem based 和 Block based 两种不同类型 Plugin。除此之外，Cinder Plugins 还提供了 iSCSC、FC、NFS 等常用的数据传输协议 Plugin 框架，上传逻辑得以根据实际情况来使用（Attached/Dettached）存储资源。</li>
</ul>
<h5>cinder-backup</h5>
<ul>
<li>提供 Volume 的备份功能，支持将 Volume 备份到对象存储中（e.g. Swift、Ceph、IBM TSM、NFS），也支持从备份 Restore 成为 Volume。</li>
</ul>
<h4>参考链接</h4>
<ul>
<li><a href="https://docs.openstack.org/cinder/latest/">[1] OpenStack: Cinder官方文档</a></li>
<li><a href="https://www.cnblogs.com/luohaixian/p/8134967.html">[2] 博客园：Cinder 组件解析</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/34634620">[3] ZhiHu: OpenStack-Cinder </a></li>
<li><a href="https://github.com/openstack/cinder">[4] Github Repo: OpenStack/Cinder</a></li>
<li><a href="http://www.99cloud.net/10758.html%EF%BC%8F">[5] 九州云：CINDER 架构分析、高可用部署与核心功能解析</a></li>
<li><a href="https://www.cnblogs.com/jmilkfan-fanguiju/p/10589720.html">[6] 博客园：Cinder 架构分析、高可用部署与核心功能解析</a></li>
</ul>